package controllers

import (
	"cabinet/model"
	"cabinet/service"
	"cabinet/util"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"net/http"
	"time"
)

type CabinetController struct {
	DB         *gorm.DB
	MQTTClient *util.MQTTClient
	LogService *service.LogService
}

// 存物请求
type StorageRequest struct {
	PhoneNumber string `json:"phone_number" binding:"required"`
}

// 取物请求
type PickupRequest struct {
	QRCode string `json:"qr_code" binding:"required"`
}

// Store 存物接口
func (c *CabinetController) Store(ctx *gin.Context) {
	var req StorageRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request parameters"})
		return
	}
	// 查找空闲的柜子
	var cabinet model.Cabinet
	if err := c.DB.Where("status = ?", false).First(&cabinet).Error; err != nil {
		ctx.JSON(http.StatusNotFound, gin.H{"error": "No available cabinet"})
		return
	}

	// 生成取件二维码（这里使用简单的时间戳+柜号作为示例）
	qrCode := time.Now().Unix() + int64(cabinet.ID)

	// 发送开柜命令
	if err := c.MQTTClient.SendOpenCommand(cabinet.Code); err != nil {
		// 记录错误日志
		c.LogService.RecordCabinetError(
			cabinet.ID,
			"hardware",
			"Failed to open cabinet",
			err.Error(),
		)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to open cabinet"})
		return
	}

	// 更新柜子状态
	cabinet.Status = true
	cabinet.QRCode = string(qrCode)
	cabinet.StorageTime = time.Now()
	if err := c.DB.Save(&cabinet).Error; err != nil {
		// 记录错误日志
		c.LogService.RecordCabinetError(
			cabinet.ID,
			"system",
			"Failed to update cabinet status",
			err.Error(),
		)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update cabinet status"})
		return
	}

	// 创建存储记录
	record := model.CabinetRecord{
		CabinetID:   cabinet.ID,
		PhoneNumber: req.PhoneNumber,
		Status:      0,
		StoreTime:   time.Now(),
	}

	if err := c.DB.Create(&record).Error; err != nil {
		// 记录错误日志
		c.LogService.RecordCabinetError(
			cabinet.ID,
			"system",
			"Failed to create storage record",
			err.Error(),
		)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create storage record"})
		return
	}
	// 记录操作日志
	c.LogService.RecordCabinetOperation(
		cabinet.ID,
		0, // 用户ID，这里暂时为0
		req.PhoneNumber,
		"store",
		"User stored items in cabinet",
	)

	// 等待柜子状态反馈（可以设置超时）
	time.Sleep(2 * time.Second)

	ctx.JSON(http.StatusOK, gin.H{
		"message":        "Storage successful",
		"qr_code":        qrCode,
		"cabinet_number": cabinet.Code,
	})

	// 发送关柜命令
	if err := c.MQTTClient.SendCloseCommand(cabinet.Code); err != nil {
		// 记录错误日志
		c.LogService.RecordCabinetError(
			cabinet.ID,
			"hardware",
			"Failed to close cabinet",
			err.Error(),
		)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to close cabinet"})
		return
	}

	ctx.JSON(http.StatusOK, model.StorageResponse{
		Message:       "Storage successful",
		QRCode:        string(qrCode),
		CabinetNumber: cabinet.Code,
	})
}

// Pickup 取物接口
func (c *CabinetController) Pickup(ctx *gin.Context) {
	var req PickupRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request parameters"})
		return
	}

	// 查找对应的柜子
	var cabinet model.Cabinet
	if err := c.DB.Where("qr_code = ? AND status = ?", req.QRCode, true).First(&cabinet).Error; err != nil {
		ctx.JSON(http.StatusNotFound, gin.H{"error": "Invalid QR code or cabinet not found"})
		return
	}

	// 查找存储记录
	var record model.CabinetRecord
	if err := c.DB.Where("cabinet_id = ? AND status = ?", cabinet.ID, 0).First(&record).Error; err != nil {
		ctx.JSON(http.StatusNotFound, gin.H{"error": "Storage record not found"})
		return
	}
	// 检查是否过期
	if time.Now().After(record.ExpireTime) {
		// 记录过期日志
		c.LogService.RecordCabinetError(
			cabinet.ID,
			"business",
			"Storage record expired",
			"User did not pickup items within 24 hours",
		)
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "Storage record expired"})
		return
	}

	// 发送开柜命令
	if err := c.MQTTClient.SendOpenCommand(cabinet.Code); err != nil {
		// 记录错误日志
		c.LogService.RecordCabinetError(
			cabinet.ID,
			"hardware",
			"Failed to open cabinet",
			err.Error(),
		)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to open cabinet"})
		return
	}

	// 更新柜子状态
	cabinet.Status = false
	cabinet.QRCode = ""
	cabinet.RetrievalTime = new(time.Time)
	*cabinet.RetrievalTime = time.Now()
	cabinet.Duration = time.Since(cabinet.StorageTime)

	if err := c.DB.Save(&cabinet).Error; err != nil {
		// 记录错误日志
		c.LogService.RecordCabinetError(
			cabinet.ID,
			"system",
			"Failed to update cabinet status",
			err.Error(),
		)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update cabinet status"})
		return
	}

	// 更新存储记录
	record.Status = 1
	record.PickupTime = time.Now()
	if err := c.DB.Save(&record).Error; err != nil {
		// 记录错误日志
		c.LogService.RecordCabinetError(
			cabinet.ID,
			"system",
			"Failed to update storage record",
			err.Error(),
		)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update storage record"})
		return
	}

	// 记录操作日志
	c.LogService.RecordCabinetOperation(
		cabinet.ID,
		0, // 用户ID，这里暂时为0
		record.PhoneNumber,
		"pickup",
		"User picked up items from cabinet",
	)

	// 等待柜子状态反馈（可以设置超时）
	time.Sleep(2 * time.Second)
	ctx.JSON(http.StatusOK, gin.H{
		"message":        "Pickup successful",
		"qr_code":        cabinet.Code,
		"cabinet_number": cabinet.Duration.String(),
	})

	// 发送关柜命令
	if err := c.MQTTClient.SendCloseCommand(cabinet.Code); err != nil {
		// 记录错误日志
		c.LogService.RecordCabinetError(
			cabinet.ID,
			"hardware",
			"Failed to close cabinet",
			err.Error(),
		)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to close cabinet"})
		return
	}

	ctx.JSON(http.StatusOK, model.PickupResponse{
		Message:       "Pickup successful",
		CabinetNumber: cabinet.Code,
		Duration:      cabinet.Duration,
	})
}
